/**
 * 
 */
package com.wistech.solr.elevation;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang.StringUtils;
import org.apache.lucene.index.IndexReader;
import org.apache.solr.common.SolrException;
import org.apache.solr.core.SolrCore;

/**
 * @author Liuye
 * 
 */
public class RedisQueryElevationComponent extends
		AbstractQueryElevationComponent {
	private static final String REDIS_HOST = "redis-host";
	private static final String REDIS_PORT = "redis-port";
	private static final String REDIS_DBINDEX = "redis-dbindex";
	private RedisElevation redisElevation;
	private Map<String, ElevationBean> elevationCache;
	private String coreElevateKey;

	@Override
	public void inform(SolrCore core) {
		super.inform(core);
		coreElevateKey = core.getName() + ".elevate";
		String redisHost = initArgs
				.get(RedisQueryElevationComponent.REDIS_HOST);
		if (StringUtils.isBlank(redisHost)) {
			throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
					"QueryElevationComponent must specify argument: '"
							+ REDIS_HOST + "' --  ip of redis");
		}
		int redisPort = initArgs.getInt(
				RedisQueryElevationComponent.REDIS_PORT,
				RedisElevation.NONE_REDIS_PORT);

		int dbIndex = initArgs.getInt(
				RedisQueryElevationComponent.REDIS_DBINDEX, 0);

		redisElevation = new RedisElevation(redisHost, redisPort, dbIndex,
				coreElevateKey);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.wistech.solr.elevation.AbstractQueryElevationComponent#getElevationMap
	 * (org.apache.lucene.index.IndexReader, org.apache.solr.core.SolrCore)
	 */
	@Override
	protected Map<String, ElevationBean> getElevationMap(IndexReader reader,
			SolrCore core) throws Exception {
		if (elevationCache == null) {
			elevationCache = loadElevationMap();
		}
		return elevationCache;
	}

	public void refresh() throws IOException {
		elevationCache = loadElevationMap();
	}

	private Map<String, ElevationBean> loadElevationMap() throws IOException {
		Map<String, ElevationBean> map = new ConcurrentHashMap<String, ElevationBean>();

		Map<String, List<Elevation>> redisElevations = redisElevation.getAll();
		for (Map.Entry<String, List<Elevation>> entry : redisElevations
				.entrySet()) {
			String qstr = entry.getKey();
			List<Elevation> elevationList = entry.getValue();
			if (elevationList != null && !elevationList.isEmpty()) {
				ArrayList<String> include = new ArrayList<String>();
				ArrayList<String> exclude = new ArrayList<String>();
				for (Elevation elevation : elevationList) {
					if (elevation.isExclude()) {
						exclude.add(elevation.getId());
						continue;
					}
					include.add(elevation.getId());
				}
				ElevationBean elev = new ElevationBean(qstr, include, exclude);
				map.put(elev.analyzed, elev);
			}
		}
		return map;
	}
}
